package pluginUtils;


public class limMatrix {
	private limComplexe a,b,c,d;

	/**
	 * @param a
	 * @param b
	 * @param c
	 * @param d
	 */
	public limMatrix(limComplexe a, limComplexe b, limComplexe c, limComplexe d) {
		super();
		this.a = a;
		this.b = b;
		this.c = c;
		this.d = d;
	}

	/**
	 * @return the a
	 */
	public limComplexe getA() {
		return a;
	}

	/**
	 * @param a the a to set
	 */
	public void setA(limComplexe a) {
		this.a = a;
	}

	/**
	 * @return the b
	 */
	public limComplexe getB() {
		return b;
	}

	/**
	 * @param b the b to set
	 */
	public void setB(limComplexe b) {
		this.b = b;
	}

	/**
	 * @return the c
	 */
	public limComplexe getC() {
		return c;
	}

	/**
	 * @param c the c to set
	 */
	public void setC(limComplexe c) {
		this.c = c;
	}

	/**
	 * @return the d
	 */
	public limComplexe getD() {
		return d;
	}

	/**
	 * @param d the d to set
	 */
	public void setD(limComplexe d) {
		this.d = d;
	} 
	
	public limComplexe det(){
		limComplexe z1=limComplexe.mul(this.a,this.d); 
		limComplexe z2=limComplexe.mul(this.b,this.c);
		return limComplexe.sub(z1,z2);
	}
	
	
	public limMatrix make_s12(){
		limComplexe d1=limComplexe.recip(this.det().cx_sqrt()); 
		return new limMatrix(limComplexe.mul(this.a,d1),
				             limComplexe.mul(this.b,d1),
				             limComplexe.mul(this.c,d1),
				             limComplexe.mul(this.d,d1)); 
	}
	
	public limMatrix conjmat(){
		return new limMatrix(this.a.conj(),this.b.conj(),this.c.conj(),this.d.conj()); 
	}
	
	public limMatrix inverse(){
		limComplexe d1=this.det(); 
		limComplexe za=this.d;
		limComplexe zb=limComplexe.createComplexeFromRI(-this.b.getReal(),-this.b.getIm()); 
		limComplexe zc=limComplexe.createComplexeFromRI(-this.c.getReal(),-this.c.getIm());
		limComplexe zd=new limComplexe(this.a); 
		if(d1.getReal()>0) return new limMatrix(za,zb,zc,zd);
		za.setReal(-za.getReal()); 
		zb.setReal(-zb.getReal()); 
		zc.setReal(-zc.getReal()); 
		zd.setReal(-zd.getReal()); 
		return new limMatrix(za,zb,zc,zd);
	}
	
	public limMatrix product(limMatrix deuze){
		limComplexe d1=this.det();
		limMatrix arg2=deuze; 
		if(d1.getReal()<0) arg2=deuze.conjmat(); 
		limComplexe za=limComplexe.add(limComplexe.mul(this.a,arg2.a),limComplexe.mul(this.b,arg2.c));
		limComplexe zb=limComplexe.add(limComplexe.mul(this.a,arg2.b),limComplexe.mul(this.b,arg2.d));
		limComplexe zc=limComplexe.add(limComplexe.mul(this.c,arg2.a),limComplexe.mul(this.d,arg2.c));
		limComplexe zd=limComplexe.add(limComplexe.mul(this.c,arg2.b),limComplexe.mul(this.d,arg2.d));
		return new limMatrix(za,zb,zc,zd); 
	}
	
	public limMatrix circleToMatrix(limCircle circ){
		if(circ.getRadius()<0) return lineToMatrix(circ); 
		limComplexe za=limComplexe.mulbyDouble(circ.getCenter(),1/circ.getRadius()); 
		limComplexe zb=limComplexe.createComplexeFromRI(circ.getRadius()-circ.getCenter().squareNorm()/circ.getRadius(),0);
		limComplexe zc=limComplexe.createComplexeFromRI(1/circ.getRadius(),0);
		limComplexe zd=limComplexe.mulbyDouble(circ.getCenter(),circ.getRadius()); 
		return new limMatrix(za,zb,zc,zd);
	}
	
	public limMatrix lineToMatrix(limCircle circ){
		limComplexe unit=limComplexe.createComplexeFromRI(Math.cos(-Math.PI*circ.getRadius()),Math.sin(-Math.PI*circ.getRadius()));
		limComplexe I=limComplexe.createComplexeFromRI(0, 1); 
		limComplexe za=limComplexe.mul(I,unit);
		limComplexe zb1=limComplexe.sub(limComplexe.mul(unit.conj(),circ.getCenter()),limComplexe.mul(unit, circ.getCenter().conj()));
		limComplexe zb=limComplexe.mul(I, zb1); 
		limComplexe zc=limComplexe.ZERO; 
		limComplexe zd=limComplexe.mul(I,unit.conj());
		return new limMatrix(za,zb,zc,zd); 
	}
	
	public limCircle matrixToCircle(){
		if((this.c.getReal()<limConstants.LINEFUZZ)&&(this.c.getReal()>-limConstants.LINEFUZZ))
				return this.matrixToLine(); 
		limComplexe cent=limComplexe.div(this.a,this.c);
		double rayon=1/this.c.getReal(); 
		return new limCircle(rayon,cent); 
	}
	
	public limCircle matrixToLine(){
		double rayon=-this.a.arg()/Math.PI-1.5; 
		limComplexe cent=limComplexe.mulbyDouble(this.b,-0.5);
		limComplexe cent2=limComplexe.mul(cent,this.a);
		return new limCircle(rayon,cent2); 
	}
	
	public limCircle imageCircle(limCircle c){
		limMatrix y=this.circleToMatrix(c); 
		limMatrix xi=this.inverse(); 
		limMatrix y1=y.product(xi);
		limMatrix y2=this.product(y1);
		return y2.matrixToCircle(); 
	}
	
	
	

}
